#include "Belt.h"
#include "GameMap.h"

Belt::Belt(GridVec pos, int name, int direction)
    : Building(pos, name, direction)
{
    switch (name)
    {
        case BuildingType::BELT_A:
        case BuildingType::BELT_D:
        case BuildingType::BELT_S:
        case BuildingType::BELT_W:
            in = direction;
            break;
        case BuildingType::BELT_A_S:
        case BuildingType::BELT_A_W:
            in = LEFT;
            break;
        case BuildingType::BELT_D_S:
        case BuildingType::BELT_D_W:
            in = RIGHT;
            break;
        case BuildingType::BELT_S_A:
        case BuildingType::BELT_S_D:
            in = DOWN;
            break;
        case BuildingType::BELT_W_A:
        case BuildingType::BELT_W_D:
            in = UP;
            break;
        default:
            break;
    }
    out = direction;
    FirstRequire_ms = 1500;
    SecondRequire_ms = 720;
    switch (name)
    {
        case BuildingType::BELT_W:
        case BuildingType::BELT_W_A:
        case BuildingType::BELT_W_D:
            init_x = pos.j * GameInfo::CELLSIZE + GameInfo::CELLSIZE / 2;
            init_y = pos.i * GameInfo::CELLSIZE + GameInfo::CELLSIZE;
            break;
        case BuildingType::BELT_A:
        case BuildingType::BELT_A_S:
        case BuildingType::BELT_A_W:
            init_x = pos.j * GameInfo::CELLSIZE + GameInfo::CELLSIZE;
            init_y = pos.i * GameInfo::CELLSIZE + GameInfo::CELLSIZE / 2;
            break;
        case BuildingType::BELT_S:
        case BuildingType::BELT_S_A:
        case BuildingType::BELT_S_D:
            init_x = pos.j * GameInfo::CELLSIZE + GameInfo::CELLSIZE / 2;
            init_y = pos.i * GameInfo::CELLSIZE;
            break;
        case BuildingType::BELT_D:
        case BuildingType::BELT_D_S:
        case BuildingType::BELT_D_W:
            init_x = pos.j * GameInfo::CELLSIZE;
            init_y = pos.i * GameInfo::CELLSIZE + GameInfo::CELLSIZE / 2;
            break;
        default:
            break;
    }
}

bool Belt::CanReceive(GridVec target, int directionin, int shapename)
{
    if (state == TickableStatus::EMPTY)
    {
        if (directionin == in)
        {
            return true;
        }
    }
    return false;
}

std::vector<GridVec> Belt::BuildingAllPos()
{
    std::vector<GridVec> result = {pos};
    return result;
}

void Belt::Receive(GridVec target, int directionin, int shapename)
{
    shape.name = shapename;
    shape.x0 = init_x;
    shape.y0 = init_y;
    state = TickableStatus::RUNNING;
    timer.Reset();
}

void Belt::TickableRunning()
{
    double offset = (running_ms * GameInfo::CELLSIZE) / FirstRequire_ms;
    switch (name)
    {
        case BuildingType::BELT_A:
        {
            shape.x0 = init_x - offset;
            shape.y0 = init_y;
            break;
        }
        case BuildingType::BELT_D:
        {
            shape.x0 = init_x + offset;
            shape.y0 = init_y;
            break;
        }
        case BuildingType::BELT_S:
        {
            shape.y0 = init_y + offset;
            shape.x0 = init_x;
            break;
        }
        case BuildingType::BELT_W:
        {
            shape.y0 = init_y - offset;
            shape.x0 = init_x;
            break;
        }
        case BuildingType::BELT_A_S:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x - offset;
                shape.y0 = init_y;
            }
            else
            {
                shape.x0 = init_x - GameInfo::CELLSIZE / 2;
                shape.y0 = init_y + (offset - GameInfo::CELLSIZE / 2);
            }
            break;
        }
        case BuildingType::BELT_A_W:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x - offset;
                shape.y0 = init_y;
            }
            else
            {
                shape.x0 = init_x - GameInfo::CELLSIZE / 2;
                shape.y0 = init_y - (offset - GameInfo::CELLSIZE / 2);
            }
            break;
        }
        case BuildingType::BELT_D_S:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x + offset;
                shape.y0 = init_y;
            }
            else
            {
                shape.y0 = init_y + (offset - GameInfo::CELLSIZE / 2);
                shape.x0 = init_x + GameInfo::CELLSIZE / 2;
            }
            break;
        }
        case BuildingType::BELT_D_W:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x + offset;
                shape.y0 = init_y;
            }
            else
            {
                shape.y0 = init_y - (offset - GameInfo::CELLSIZE / 2);
                shape.x0 = init_x + GameInfo::CELLSIZE / 2;
            }
            break;
        }
        case BuildingType::BELT_S_A:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x;
                shape.y0 = init_y + offset;
            }
            else
            {
                shape.x0 = init_x - (offset - GameInfo::CELLSIZE / 2);
                shape.y0 = init_y + GameInfo::CELLSIZE / 2;
            }
            break;
        }
        case BuildingType::BELT_S_D:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x;
                shape.y0 = init_y + offset;
            }
            else
            {
                shape.x0 = init_x + (offset - GameInfo::CELLSIZE / 2);
                shape.y0 = init_y + GameInfo::CELLSIZE / 2;
            }
            break;
        }
        case BuildingType::BELT_W_A:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x;
                shape.y0 = init_y - offset;
            }
            else
            {
                shape.x0 = init_x - (offset - GameInfo::CELLSIZE / 2);
                shape.y0 = init_y - GameInfo::CELLSIZE / 2;
            }
            break;
        }
        case BuildingType::BELT_W_D:
        {
            if (running_ms < FirstRequire_ms / 2)
            {
                shape.x0 = init_x;
                shape.y0 = init_y - offset;
            }
            else
            {
                shape.x0 = init_x + (offset - GameInfo::CELLSIZE / 2);
                shape.y0 = init_y - GameInfo::CELLSIZE / 2;
            }
            break;
        }
        default:
            break;
    }
}
void Belt::UpdateTickableState(GameMap &gamemap)
{
    switch (state)
    {
        case TickableStatus::EMPTY:
        {
            running_ms = 0;
            break;
        }
        case TickableStatus::RUNNING:
        {
            timer.UpdateRuningTime(FirstRequire_ms);
            running_ms = timer.runningMs;
            if (running_ms > FirstRequire_ms)
            {
                running_ms = FirstRequire_ms;
            }
            if (running_ms >= FirstRequire_ms)
            {
                // 运输到传送带末尾了，准备传递给下一个建筑
                state = TickableStatus::BLOCK;
                running_ms = 0;
            }
            else
            {
                TickableRunning();
            }
            break;
        }
        case TickableStatus::BLOCK:
        {
            if (CanSend(pos, direction, shape.name, gamemap))
            {
                Send(pos, direction, shape.name, gamemap);
                state = TickableStatus::EMPTY;
                shape.name = NONE;
                shape.x0 = init_x;
                shape.y0 = init_y;
            }
            break;
        }
        default:
            break;
    }
    return;
}
